﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SomeGame.Actors.Components.Movement;
using SomeGame.Actors.Types;
using SomeGame.Zones;

namespace SomeGame.Actors.Components.State {

    public class PlayerStateMachine : ActorComponent {

        private State CurrentState = State.Null;
        private Animation CurrentAnimation;
        private readonly Body Body;
        private readonly PlayerMovement PlayerMovement;
        private readonly Appearance Appearance;
        private readonly IDictionary<State, Animation> Animations = new Dictionary<State, Animation>();

        public PlayerStateMachine(Animation idle, Animation walking, Animation attacking, Body body, PlayerMovement playerMovement, Appearance appearance) {
            Animations.Add(State.Idle, idle);
            Animations.Add(State.WalkingLeft, walking);
            Animations.Add(State.WalkingRight, walking);
            Animations.Add(State.Attacking, attacking);
            Body = body;
            PlayerMovement = playerMovement;
            Appearance = appearance;
            SetCurrentState(State.Idle);
        }

        public void SetCurrentState(State nextState) {
            if (CurrentState == nextState) {
                return;
            }
			// Actions based on what the Player IS doing right now.
	        switch (CurrentState) {
			    case State.Idle:
	                switch (nextState) {
	                    case State.WalkingLeft:
                            Body.FacingDirection = FacingDirection.Left;
                            PlayerMovement.Direction = new Vector2(-1, 0);
                            Appearance.SpriteEffects = SpriteEffects.FlipHorizontally;
                            break;
                        case State.WalkingRight:
                            Body.FacingDirection = FacingDirection.Right;
                            PlayerMovement.Direction = new Vector2(1, 0);
                            Appearance.SpriteEffects = SpriteEffects.None;
                            break;
	                }
					break;
                case State.WalkingLeft:
	                switch (nextState) {
                        case State.WalkingRight:
                            Body.FacingDirection = FacingDirection.Right;
                            PlayerMovement.Direction = new Vector2(1, 0);
                            Appearance.SpriteEffects = SpriteEffects.None;
                            break;
	                }
	                break;
                case State.WalkingRight:
	                switch (nextState) {
	                    case State.WalkingLeft:
                            Body.FacingDirection = FacingDirection.Left;
                            PlayerMovement.Direction = new Vector2(-1, 0);
                            Appearance.SpriteEffects = SpriteEffects.FlipHorizontally;
                            break;
	                }
	                break;
                case State.WaitingForAttackToComplete:
	                switch (nextState) {
	                    case State.Attacking:
	                    case State.WalkingLeft:
	                    case State.WalkingRight:
	                        return;
	                }
	                break;
				case State.Attacking:
	                switch (nextState) {
	                    case State.WalkingLeft:
	                    case State.WalkingRight:
	                        return;
	                }
	                break;
	        }
			// Actions based on what the Player WILL BE doing after the transition.
	        switch (nextState) {
			    case State.Idle:
					Stop();
					break;
                case State.WalkingLeft:
	                break;
                case State.WalkingRight:
	                break;
                case State.WaitingForAttackToComplete:
	                break;
				case State.Attacking:
					Stop();
					break;
	        }
            if (Animations.ContainsKey(nextState)) { // States are not required to have animations.
                CurrentAnimation = Animations[nextState];
                CurrentAnimation.SetInitialFrame();
            }
            CurrentState = nextState;
        }

		private void Stop() {
			PlayerMovement.Direction = Vector2.Zero;
			PlayerMovement.CurrentSpeed = 0;
		}
        
        public override void Update(GameTime gameTime, bool parallax) {
            switch (CurrentState) {
                case State.WaitingForAttackToComplete: // Wait for attack Animation to finish then Idle.
                    if (CurrentAnimation.IsAboutToShowFirstFrame()) {
						SetCurrentState(State.Idle);
                    }
                    break;
                case State.Attacking:
                    if (CurrentAnimation.IsAboutToShowFirstFrame()) {
                        ZoneManager.CurrentZone.SoundEffectInstances["Shotgun"].Play();
				        PhysicsEngine.DoBulletCollision(Body, ZoneManager.CurrentZone.PlayerLevelActors.Where(x => x is Zombie).ToList());
                    }
                    break;
            }
            CurrentAnimation.Update(gameTime, parallax);
        }

        public enum State {

            Null,
			Idle,
			WalkingLeft,
			WalkingRight,
            WaitingForAttackToComplete,
			Attacking,
			TakingHit,
			Dying,
			Gibbed,
			Dead

		}

    }

}